﻿using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;

namespace Narwhunderful.Aphelia.Framework.IO.Serialization
{

    public sealed class TypeNameConverter : ITypeNameConverter
    {

        private readonly Dictionary<Type, string> _cache = new Dictionary<Type, string>();

        public TypeNameConverter()
        {
        }

        public TypeNameConverter(bool includeAssemblyVersion, bool includeCulture, bool includePublicKeyToken)
        {
            IncludeAssemblyVersion = includeAssemblyVersion;
            IncludeCulture = includeCulture;
            IncludePublicKeyToken = includePublicKeyToken;
        }

        public bool IncludeAssemblyVersion { get; private set; }
        public bool IncludeCulture { get; private set; }
        public bool IncludePublicKeyToken { get; private set; }

        public string ConvertToTypeName(Type type)
        {
            if (type == null) return string.Empty;

            // Search in cache
            if (_cache.ContainsKey(type))
            {
                return _cache[type];
            }

            string typename = type.AssemblyQualifiedName;

            if (!IncludeAssemblyVersion)
            {
                typename = RemoveAssemblyVersion(typename);
            }

            if (!IncludeCulture)
            {
                typename = RemoveCulture(typename);
            }

            if (!IncludePublicKeyToken)
            {
                typename = RemovePublicKeyToken(typename);
            }

            // Adding to cache
            _cache.Add(type, typename);

            return typename;
        }

        public Type ConvertToType(string typeName)
        {
            if (string.IsNullOrEmpty(typeName)) return null;
            Type type = Type.GetType(typeName, true);
            return type;
        }

        private static string RemovePublicKeyToken(string typename)
        {
            return Regex.Replace(typename, @", PublicKeyToken=\w+", string.Empty);
        }

        private static string RemoveCulture(string typename)
        {
            return Regex.Replace(typename, @", Culture=\w+", string.Empty);
        }

        private static string RemoveAssemblyVersion(string typename)
        {
            return Regex.Replace(typename, @", Version=\d+.\d+.\d+.\d+", string.Empty);
        }
    }
}
